import { IDMap } from "../../Framework/Util/IDMap";
import { IKeepActivePrxHelper } from "./IKeepActivePrxHelper";
import { IKeepActivePrx } from "./IKeepActivePrx";
import { RMIConnection } from "./RMIConnection";
import { Communicator } from "./Communicator";
import { IMessageHandler } from "../../Framework/MQ/IMessageHandler";
import { RMIObjectBind } from "./RMIObjectBind";
import { SIdentity } from "./SIdentity";
import { RMIObject } from "./RMIObject";
import { MessageBlock } from "../../Framework/MQ/MessageBlock";
import { SerializeStream } from "../../Framework/Serialize/SerializeStream";
import { Context } from "./Context";
import { ERMIDispatchStatus } from "./ERMIDispatchStatus";
import { ERMIMessageType } from "./ERMIMessageType";
import { Outgoing } from "./Outgoing";
import { ArrayHolder } from "../../Framework/Holder/ArrayHolder";
type int = number;
//class Session

export class Session {
  constructor() {
    this._messageWaitToSend = new Array<any>();
    this._bindingObject = new Array<any>();
    this._messageMap = new IDMap();
    this._keepActivePrx = new IKeepActivePrxHelper();
    this._keepActivePrx.bindingSession(this);
  }

  public get keepActivePrx(): IKeepActivePrx {
    return this._keepActivePrx;
  }

  public get connection(): RMIConnection {
    return this._connection;
  }

  public set connection(conn: RMIConnection) {
    this._connection = conn;
    return;
  }

  public get communicator(): Communicator {
    return this._communicator;
  }

  public set communicator(comtor: Communicator) {
    this._communicator = comtor;
    return;
  }

  public get name(): string {
    return this._name;
  }

  public set name(arg1: string) {
    this._name = arg1;
    return;
  }

  public get messageHandler(): IMessageHandler {
    return this._messageHandler;
  }

  public set messageHandler(handler: IMessageHandler) {
    this._messageHandler = handler;
    return;
  }

  public bindCommunicator(communicator: Communicator): void {
    if (this._connection != null) {
      this._connection.close();
      // @ts-ignore
      this._connection = null;
    }
    this.communicator = communicator;
    this.communicator.session = this;
    return;
  }

  public removeBackObject(arg1: int): Boolean {
    return this._messageMap.remove(arg1);
  }

  public findRemoveBackObject(arg1: int) {
    var loc1 = this._messageMap.findAndRemove(arg1) as RMIObjectBind;
    if (null != loc1) {
      loc1.resertTimer();
    }
    return loc1;
  }

  public addBackObject(arg1: RMIObjectBind, arg2: int): int {
    var loc1 = this._messageMap.insert(arg1);
    if (loc1 > 0) {
      arg1.initTimer(arg2);
    }
    return loc1;
  }

  public findObject(sidentity: SIdentity) {
    var i = 0;
    while (i < this._bindingObject.length) {
      let rimiObject = this._bindingObject[i] as RMIObject;
      if (rimiObject.identity.name == sidentity.name) {
        return rimiObject;
      }
      ++i;
    }
    return null;
  }

  public bindingObject(sidentity: SIdentity, rmiObject: RMIObject) {
    var i = 0;
    while (i < this._bindingObject.length) {
      let rmiObject = this._bindingObject[i] as RMIObject;
      if (rmiObject.identity.name == sidentity.name) {
        return false;
      }
      ++i;
    }
    rmiObject.identity = sidentity;
    this._bindingObject.push(rmiObject);
    return true;
  }

  public remove(sidentity: SIdentity) {
    var rmiObject = null;
    var i = 0;
    while (i < this._bindingObject.length) {
      rmiObject = this._bindingObject[i] as RMIObject;
      if (rmiObject.identity.name == sidentity.name) {
        this._bindingObject.splice(i, 1);
        return true;
      }
      ++i;
    }
    return false;
  }

  public pushMessage(messageBlock: MessageBlock): void {
    var stream = new SerializeStream();
    var context = new Context();
    context._session = this;
    context._connection = this.connection;
    context._messageId = 0;
    context._dispachStatus = ERMIDispatchStatus.DispatchAsync;
    context._messageType = ERMIMessageType.MessageTypeMQ;
    messageBlock.__write(stream);
    Outgoing.invokeAsyncNoBack(context, null, stream);
  }

  public pinkMessage(arg1: ArrayHolder): void {
    arg1.value = this._messageWaitToSend;
    this._messageWaitToSend = new Array<any>();
  }

  public pinkRemoveMessage(arg1: ArrayHolder): void {
    var messageId = null;
    arg1.value = new Array<any>();
    var t = 0;
    var i = 0;
    while (i < this._messageWaitToSend.length) {
      messageId = this.findRemoveBackObject(
        (this._messageWaitToSend[i] as RMIObjectBind).messageId
      );
      if (null != messageId) {
        messageId.resertTimer();
        arg1.value[t++] = messageId;
      }
      ++i;
    }
    this._messageWaitToSend = new Array<any>();
    return;
  }

  public addMessage(arg1: RMIObjectBind): void {
    this._messageWaitToSend.push(arg1);
    return;
  }

  public abandon(): void {
    if (this._connection != null) {
      this._connection.close();
      // @ts-ignore
      this._connection = null;
    }
    this._messageMap = new IDMap();
    this._messageWaitToSend = new Array<any>();
    this._bindingObject = new Array<any>();
    return;
  }

  private /* var */ _communicator!: Communicator;

  private /* var */ _connection!: RMIConnection;

  private /* var */ _messageMap: IDMap;

  private /* var */ _messageWaitToSend: Array<any>;

  private /* var */ _bindingObject: Array<RMIObject>;

  private /* var */ _keepActivePrx: IKeepActivePrxHelper;

  private /* var */ _name!: string;

  private /* var */ _messageHandler!: IMessageHandler;
}
